home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Blender 2.49b / blender-2.49b-windows.exe / $_4_ / .blender / scripts / config.py < prev    next >
Text File  |  2009-08-31  |  23KB  |  802 lines

  1. #!BPY
  2.  
  3. """
  4. Name: 'Scripts Config Editor'
  5. Blender: 236
  6. Group: 'System'
  7. Tooltip: 'View and edit available scripts configuration data'
  8. """
  9.  
  10. __author__ = "Willian P. Germano"
  11. __version__ = "0.1 2005/04/14"
  12. __email__ = ('scripts', 'Author, wgermano:ig*com*br')
  13. __url__ = ('blender', 'blenderartists.org')
  14.  
  15. __bpydoc__ ="""\
  16. This script can be used to view and edit configuration data stored
  17. by other scripts.
  18.  
  19. Technical: this data is saved as dictionary keys with the
  20. Blender.Registry module functions.  It is persistent while Blender is
  21. running and, if the script's author chose to, is also saved to a file
  22. in the scripts config data dir.
  23.  
  24. Usage:
  25.  
  26. - Start Screen:
  27.  
  28. To access any available key, select it from (one of) the menu(s).
  29.  
  30. Hotkeys:<br>
  31.    ESC or Q: [Q]uit<br>
  32.    H: [H]elp
  33.  
  34. - Keys Config Screen:
  35.  
  36. This screen exposes the configuration data for the chosen script key.  If the
  37. buttons don't fit completely on the screen, you can scroll up or down with
  38. arrow keys or a mouse wheel.  Leave the mouse pointer over any button to get
  39. a tooltip about that option.
  40.  
  41. Any change can be reverted -- unless you have already applied it.
  42.  
  43. If the key is already stored in a config file, there will be a toggle button
  44. (called 'file') that controls whether the changes will be written back to
  45. the file or not.  If you just want to change the configuration for the current
  46. session, simply unset that button.  Note, though, that data from files has
  47. precedence over those keys already loaded in Blender, so if you re-run this
  48. config editor, unsaved changes will not be seen.
  49.  
  50. Hotkeys:<br>
  51.    ESC: back to Start Screen<br>
  52.    Q: [Q]uit<br>
  53.    U: [U]ndo changes<br>
  54.    ENTER: apply changes (can't be reverted, then)<br>
  55.    UP, DOWN Arrows and mouse wheel: scroll text up / down
  56.  
  57. Notes:
  58.  
  59. a) Available keys are determined by which scripts you use.  If the key you
  60. expect isn't available (or maybe there are none or too few keys), either the
  61. related script doesn't need or still doesn't support this feature or the key
  62. has not been stored yet, in which case you just need to run that script once
  63. to make its config data available.
  64.  
  65. b) There are two places where config data files can be saved: the
  66. bpydata/config/ dir (1) inside the default scripts dir or (2) inside the user
  67. defined Python scripts dir
  68. (User Preferences window -> File Paths tab -> Python path).  If available,
  69. (2) is the default and also the recommended option, because then fresh Blender
  70. installations won't delete your config data.  To use this option, simply set a
  71. dir for Python scripts at the User Preferences window and make sure this dir
  72. has the subdirs bpydata/ and bpydata/config/ inside it.
  73.  
  74. c) The key called "General" in the "Other" menu has general config options.
  75. All scripts where that data is relevant are recommended to access it and set
  76. behaviors accordingly.
  77. """
  78.  
  79. # $Id: config.py 16999 2008-10-09 22:28:44Z ianwill $
  80. #
  81. # --------------------------------------------------------------------------
  82. # config.py version 0.1 2005/04/08
  83. # --------------------------------------------------------------------------
  84. # ***** BEGIN GPL LICENSE BLOCK *****
  85. #
  86. # Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
  87. #
  88. # This program is free software; you can redistribute it and/or
  89. # modify it under the terms of the GNU General Public License
  90. # as published by the Free Software Foundation; either version 2
  91. # of the License, or (at your option) any later version.
  92. #
  93. # This program is distributed in the hope that it will be useful,
  94. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  95. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  96. # GNU General Public License for more details.
  97. #
  98. # You should have received a copy of the GNU General Public License
  99. # along with this program; if not, write to the Free Software Foundation,
  100. # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  101. #
  102. # ***** END GPL LICENCE BLOCK *****
  103. # --------------------------------------------------------------------------
  104.  
  105. import Blender
  106. from Blender import Draw, BGL, Registry, Window, sys as bsys
  107. from Blender.Window import Theme
  108. from BPyRegistry import LoadConfigData, SaveConfigData, HasConfigData,\
  109.     BPY_KEY_IN_FILE
  110.  
  111. MAX_STR_LEN = 300 # max length for a string
  112. MAX_ITEMS_NUM = 100 # max number for each type of button
  113.  
  114. # ---
  115. # The "General" configure options key is managed from this script.
  116. verbose = True
  117. confirm_overwrite = True
  118.  
  119. tooltips = {
  120.     'verbose': 'print script messages (info, warnings, errors) to the console',
  121.     'confirm_overwrite': 'scripts should always confirm before overwriting files'
  122. }
  123.  
  124. CFG_LIST = ['verbose', 'confirm_overwrite', 'tooltips']
  125. KEY_NAME = 'General'
  126.  
  127. def update_registry():
  128.     rd = {}
  129.     for var in CFG_LIST:
  130.         exec("rd['%s']=%s" % (var, var))
  131.     Registry.SetKey(KEY_NAME, rd, True)
  132.  
  133. rd = Registry.GetKey('General', True)
  134. if rd:
  135.     try:
  136.         for var in CFG_LIST[:-1]: # no need to update tooltips
  137.             exec("%s=rd['%s']" % (var, var))
  138.     except: update_registry()
  139.  
  140. else:
  141.     update_registry()
  142. # ---
  143.  
  144. # script globals:
  145. CFGKEY = ''
  146. LABELS = []
  147. GD = {} # groups dict (includes "Other" for unmapped keys)
  148. INDEX = 0 # to pass button indices to fs callbacks
  149. FREEKEY_IDX = 0 # index of set of keys not mapped to a script name
  150. KEYMENUS = []
  151. ALL_SCRIPTS = {}
  152. ALL_GROUPS = []
  153. START_SCREEN  = 0
  154. CONFIG_SCREEN = 1
  155. DISK_UPDATE = True # write changed data to its config file
  156.  
  157. ACCEPTED_TYPES = [bool, int, float, str, unicode]
  158.  
  159. SCREEN = START_SCREEN
  160.  
  161. SCROLL_DOWN = 0
  162.  
  163. # events:
  164. BEVT_START = 50
  165. BEVT_EXIT = 0 + BEVT_START
  166. BEVT_BACK = 1 + BEVT_START
  167. BEVT_DISK = 2 + BEVT_START
  168. BEVT_CANCEL = 3 + BEVT_START
  169. BEVT_APPLY = 4 + BEVT_START
  170. BEVT_HELP = 5 + BEVT_START
  171. BEVT_DEL = 6 + BEVT_START
  172. BEVT_KEYMENU = []
  173. BUT_KEYMENU = []
  174. BEVT_BOOL = 100
  175. BEVT_INT = BEVT_BOOL + MAX_ITEMS_NUM
  176. BEVT_FLOAT = BEVT_BOOL + 2*MAX_ITEMS_NUM
  177. BEVT_STR = BEVT_BOOL + 3*MAX_ITEMS_NUM
  178. BEVT_BROWSEDIR = BEVT_BOOL + 4*MAX_ITEMS_NUM
  179. BEVT_BROWSEFILE = BEVT_BOOL + 5*MAX_ITEMS_NUM
  180. BUT_TYPES = {
  181.     bool: 0,
  182.     int: 0,
  183.     float: 0,
  184.     str: 0
  185. }
  186.  
  187. # Function definitions:
  188.  
  189. def get_keys():
  190.     LoadConfigData() # loads all data from files in (u)scripts/bpydata/config/
  191.     return [k for k in Registry.Keys() if k[0] != "_"]
  192.  
  193.  
  194. def show_help(script = 'config.py'):
  195.     Blender.ShowHelp(script)
  196.  
  197.  
  198. def fs_dir_callback(pathname):
  199.     global CFGKEY, INDEX
  200.  
  201.     pathname = bsys.dirname(pathname)
  202.     datatypes = CFGKEY.sorteddata
  203.     datatypes[str][INDEX][1] = pathname
  204.  
  205.  
  206. def fs_file_callback(pathname):
  207.     global CFGKEY, INDEX
  208.  
  209.     datatypes = CFGKEY.sorteddata
  210.     datatypes[str][INDEX][1] = pathname
  211.  
  212.  
  213. # parse Bpymenus file to get all script filenames
  214. # (used to show help for a given key)
  215. def fill_scripts_dict():
  216.     global ALL_SCRIPTS, ALL_GROUPS
  217.  
  218.     group = ''
  219.     group_len = 0
  220.     sep = bsys.sep
  221.     home = Blender.Get('homedir')
  222.     if not home:
  223.         errmsg = """
  224. Can't find Blender's home dir and so can't find the
  225. Bpymenus file automatically stored inside it, which
  226. is needed by this script.  Please run the
  227. Help -> System -> System Information script to get
  228. information about how to fix this.
  229. """
  230.         raise SystemError, errmsg
  231.     fname = bsys.join(home, 'Bpymenus')
  232.     if not bsys.exists(fname): return False
  233.     f = file(fname, 'r')
  234.     lines = f.readlines()
  235.     f.close()
  236.     for l in lines:
  237.         if l.rfind('{') > 0:
  238.             group = l.split()[0]
  239.             ALL_GROUPS.append(group)
  240.             group_len += 1
  241.             continue
  242.         elif l[0] != "'": continue
  243.         fields = l.split("'")
  244.         if len(fields) > 2:
  245.             menuname = fields[1].replace('...','')
  246.             fields = fields[2].split()
  247.             if len(fields) > 1:
  248.                 fname = fields[1].split(sep)[-1]
  249.                 i = 1
  250.                 while not fname.endswith('.py'):
  251.                     i += 1
  252.                     fname = "%s %s" % (fname, fields[i])
  253.                 ALL_SCRIPTS[fname] = (menuname, group_len - 1)
  254.     return True
  255.  
  256.  
  257. def map_to_registered_script(name):
  258.     global ALL_SCRIPTS
  259.  
  260.     if not name.endswith('.py'):
  261.         name = "%s.py" % name
  262.     if ALL_SCRIPTS.has_key(name):
  263.         return ALL_SCRIPTS[name] # == (menuname, group index)
  264.     return None
  265.  
  266.  
  267. def reset():
  268.     global LABELS, GD, KEYMENUS, KEYS
  269.  
  270.     # init_data is recalled when a key is deleted, so:
  271.     LABELS = []
  272.     GD = {}
  273.     KEYMENUS = []
  274.     KEYS = get_keys()
  275.  
  276.  
  277. # gather all script info, fill gui menus
  278. def init_data():
  279.     global KEYS, GD, ALL_GROUPS, ALL_SCRIPTS, KEYMENUS, LABELS
  280.     global BUT_KEYMENU, BEVT_KEYMENU, FREEKEY_IDX
  281.  
  282.     for k in ALL_GROUPS:
  283.         GD[k] = []
  284.     GD[None] = []
  285.  
  286.     for k in KEYS:
  287.         res = map_to_registered_script(k)
  288.         if res:
  289.             GD[ALL_GROUPS[res[1]]].append((k, res[0]))
  290.         else: GD[None].append((k, k))
  291.  
  292.     for k in GD.keys():
  293.         if not GD[k]: GD.pop(k)
  294.  
  295.     if GD.has_key(None):
  296.         GD['Other'] = GD[None]
  297.         GD.pop(None)
  298.         FREEKEY_IDX = -1
  299.  
  300.     BUT_KEYMENU = range(len(GD))
  301.  
  302.     for k in GD.keys():
  303.         kmenu = ['Configuration Keys: %s%%t' % k]
  304.         for j in GD[k]:
  305.             kmenu.append(j[1])
  306.         kmenu = "|".join(kmenu)
  307.         KEYMENUS.append(kmenu)
  308.         LABELS.append(k)
  309.  
  310.     if FREEKEY_IDX < 0:
  311.         FREEKEY_IDX = LABELS.index('Other')
  312.  
  313.     length = len(KEYMENUS)
  314.     BEVT_KEYMENU = range(1, length + 1)
  315.     BUT_KEYMENU = range(length)
  316.  
  317.  
  318. # for theme colors:
  319. def float_colors(cols):
  320.     return map(lambda x: x / 255.0, cols)
  321.  
  322.  
  323.  
  324. class Config:
  325.  
  326.     def __init__(self, key, has_group = True):
  327.         global DISK_UPDATE
  328.  
  329.         self.key = key
  330.         self.has_group = has_group
  331.         self.name = key
  332.         self.fromdisk = HasConfigData(key) & BPY_KEY_IN_FILE
  333.         if not self.fromdisk: DISK_UPDATE = False
  334.         else: DISK_UPDATE = True
  335.  
  336.         self.origdata = Registry.GetKey(key, True)
  337.         data = self.data = self.origdata.copy()
  338.  
  339.         if not data:
  340.             Draw.PupMenu('ERROR: couldn\'t find requested data')
  341.             self.data = None
  342.             return
  343.  
  344.         keys = data.keys()
  345.         nd = {}
  346.         for k in keys:
  347.             nd[k.lower()] = k
  348.  
  349.         if nd.has_key('tooltips'):
  350.             ndval = nd['tooltips']
  351.             self.tips = data[ndval]
  352.             data.pop(ndval)
  353.         else: self.tips = 0
  354.  
  355.         if nd.has_key('limits'):
  356.             ndval = nd['limits']
  357.             self.limits = data[ndval]
  358.             data.pop(ndval)
  359.         else: self.limits = 0
  360.  
  361.         if self.has_group:
  362.             scriptname = key
  363.             if not scriptname.endswith('.py'):
  364.                 scriptname = "%s.py" % scriptname
  365.         elif nd.has_key('script'):
  366.                 ndval = nd['script']
  367.                 scriptname = data[ndval]
  368.                 data.pop(ndval)
  369.                 if not scriptname.endswith('.py'):
  370.                     scriptname = "%s.py" % scriptname
  371.         else: scriptname = None
  372.  
  373.         self.scriptname = scriptname
  374.  
  375.         self.sort()
  376.  
  377.  
  378.     def needs_update(self): # check if user changed data
  379.         data = self.data
  380.         new = self.sorteddata
  381.  
  382.         for vartype in new.keys():
  383.             for i in new[vartype]:
  384.                 if data[i[0]] != i[1]: return 1
  385.  
  386.         return 0 # no changes
  387.  
  388.  
  389.     def update(self): # update original key
  390.         global DISK_UPDATE
  391.  
  392.         data = self.data
  393.         odata = self.origdata
  394.         new = self.sorteddata
  395.         for vartype in new.keys():
  396.             for i in new[vartype]:
  397.                 if data[i[0]] != i[1]: data[i[0]] = i[1]
  398.                 if odata[i[0]] != i[1]: odata[i[0]] = i[1]
  399.  
  400.         if DISK_UPDATE: Registry.SetKey(self.key, odata, True)
  401.  
  402.     def delete(self):
  403.         global DISK_UPDATE
  404.  
  405.         delmsg = 'OK?%t|Delete key from memory'
  406.         if DISK_UPDATE:
  407.             delmsg = "%s and from disk" % delmsg
  408.         if Draw.PupMenu(delmsg) == 1:
  409.             Registry.RemoveKey(self.key, DISK_UPDATE)
  410.             return True
  411.  
  412.         return False
  413.  
  414.  
  415.     def revert(self): # revert to original key
  416.         data = self.data
  417.         new = self.sorteddata
  418.         for vartype in new.keys():
  419.             for i in new[vartype]:
  420.                 if data[i[0]] != i[1]: i[1] = data[i[0]]
  421.  
  422.  
  423.     def sort(self): # create a new dict with types as keys
  424.         global ACCEPTED_TYPES, BUT_TYPES
  425.  
  426.         data = self.data
  427.         datatypes = {}
  428.         keys = [k for k in data.keys() if k[0] != '_']
  429.         for k in keys:
  430.             val = data[k]
  431.             tval = type(val)
  432.             if tval not in ACCEPTED_TYPES: continue
  433.             if not datatypes.has_key(tval):
  434.                 datatypes[tval] = []
  435.             datatypes[type(val)].append([k, val])
  436.         if datatypes.has_key(unicode):
  437.             if not datatypes.has_key(str): datatypes[str] = datatypes[unicode]
  438.             else:
  439.                 for i in datatypes[unicode]: datatypes[str].append(i)
  440.             datatypes.pop(unicode)
  441.         for k in datatypes.keys():
  442.             dk = datatypes[k]
  443.             dk.sort()
  444.             dk.reverse()
  445.             BUT_TYPES[k] = range(len(dk))
  446.         self.sorteddata = datatypes
  447.  
  448.  
  449. # GUI:
  450.  
  451. # gui callbacks:
  452.  
  453. def gui(): # drawing the screen
  454.  
  455.     global SCREEN, START_SCREEN, CONFIG_SCREEN, KEYMENUS, LABELS
  456.     global BEVT_KEYMENU, BUT_KEYMENU, CFGKEY
  457.     global BUT_TYPES, SCROLL_DOWN, VARS_NUM
  458.  
  459.     WIDTH, HEIGHT = Window.GetAreaSize()
  460.  
  461.     theme = Theme.Get()[0]
  462.     tui = theme.get('ui')
  463.     ttxt = theme.get('text')
  464.  
  465.     COL_BG = float_colors(ttxt.back)
  466.     COL_TXT = ttxt.text
  467.     COL_TXTHI = ttxt.text_hi
  468.  
  469.     BGL.glClearColor(COL_BG[0],COL_BG[1],COL_BG[2],COL_BG[3])
  470.     BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
  471.     BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
  472.  
  473.     if SCREEN == START_SCREEN:
  474.         x = 10
  475.         y = 10
  476.         h = 20
  477.         w = 90
  478.         BGL.glRasterPos2i(x, y)
  479.         Draw.Text('Select a configuration key to access it.  Press Q or ESC to leave.')
  480.         km_len = len(KEYMENUS)
  481.         km_columns = (WIDTH - x) / w
  482.         if km_columns == 0: km_rows = km_len
  483.         else:
  484.             km_rows = km_len / km_columns
  485.             if (km_len % km_columns): km_rows += 1
  486.         if km_rows == 0: km_rows = 1
  487.         ystart = y + 2*h*km_rows
  488.         if ystart > (HEIGHT - 70): ystart = HEIGHT - 70
  489.         y = ystart
  490.         column = 1
  491.         for i, km in enumerate(KEYMENUS):
  492.             column += 1
  493.             BGL.glRasterPos2i(x + 2, y + h + 5)
  494.             Draw.Text(LABELS[i])
  495.             BUT_KEYMENU[i] = Draw.Menu(km, BEVT_KEYMENU[i],
  496.                 x, y, w - 10, h, 0, 'Choose a key to access its configuration data')
  497.             if column > km_columns:
  498.                 column = 1
  499.                 y -= 2*h
  500.                 if y < 35: break
  501.                 x = 10
  502.             else: x += w
  503.         x = 10
  504.         y = 50 + ystart
  505.         BGL.glColor3ub(COL_TXTHI[0], COL_TXTHI[1], COL_TXTHI[2])
  506.         BGL.glRasterPos2i(x, y)
  507.         Draw.Text('Scripts Configuration Editor')
  508.         Draw.PushButton('help', BEVT_HELP, x, 22, 45, 16,
  509.             'View help information about this script (hotkey: H)')
  510.  
  511.     elif SCREEN == CONFIG_SCREEN:
  512.         x = y = 10
  513.         h = 18
  514.         data = CFGKEY.sorteddata
  515.         tips = CFGKEY.tips
  516.         fromdisk = CFGKEY.fromdisk
  517.         limits = CFGKEY.limits
  518.         VARS_NUM = 0
  519.         for k in data.keys():
  520.             VARS_NUM += len(data[k])
  521.         lines = VARS_NUM + 5 # to account for header and footer
  522.         y = lines*h
  523.         if y > HEIGHT - 20: y = HEIGHT - 20
  524.         BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
  525.         BGL.glRasterPos2i(x, y)
  526.         Draw.Text('Scripts Configuration Editor')
  527.         y -= 20
  528.         BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
  529.         txtsize = 10
  530.         if HEIGHT < lines*h:
  531.             BGL.glRasterPos2i(10, 5)
  532.             txtsize += Draw.Text('Arrow keys or mouse wheel to scroll, ')
  533.         BGL.glRasterPos2i(txtsize, 5)
  534.         Draw.Text('Q or ESC to return.')
  535.         BGL.glRasterPos2i(x, y)
  536.         Draw.Text('Key: "%s"' % CFGKEY.name)
  537.         bh = 16
  538.         bw = 45
  539.         by = 16
  540.         i = -1
  541.         if CFGKEY.scriptname:
  542.             i = 0
  543.             Draw.PushButton('help', BEVT_HELP, x, by, bw, bh,
  544.                 'Show documentation for the script that owns this key (hotkey: H)')
  545.         Draw.PushButton('back', BEVT_BACK, x + (1+i)*bw, by, bw, bh,
  546.             'Back to config keys selection screen (hotkey: ESC)')
  547.         Draw.PushButton('exit', BEVT_EXIT, x + (2+i)*bw, by, bw, bh,
  548.             'Exit from Scripts Config Editor (hotkey: Q)')
  549.         Draw.PushButton('revert', BEVT_CANCEL, x + (3+i)*bw, by, bw, bh,
  550.             'Revert data to original values (hotkey: U)')
  551.         Draw.PushButton('apply', BEVT_APPLY, x + (4+i)*bw, by, bw, bh,
  552.             'Apply changes, if any (hotkey: ENTER)')
  553.         delmsg = 'Delete this data key from memory'
  554.         if fromdisk: delmsg = "%s and from disk" % delmsg
  555.         Draw.PushButton('delete', BEVT_DEL, x + (5+i)*bw, by, bw, bh,
  556.             '%s (hotkey: DELETE)' % delmsg)
  557.         if fromdisk:
  558.             Draw.Toggle("file", BEVT_DISK, x + 3 + (6+i)*bw, by, bw, bh, DISK_UPDATE,
  559.                 'Update also the file where this config key is stored')
  560.         i = -1
  561.         top = -1
  562.         y -= 20
  563.         yend = 30
  564.         if data.has_key(bool) and y > 0:
  565.             lst = data[bool]
  566.             for l in lst:
  567.                 top += 1
  568.                 i += 1
  569.                 if top < SCROLL_DOWN: continue
  570.                 y -= h
  571.                 if y < yend: break
  572.                 w = 20
  573.                 tog = data[bool][i][1]
  574.                 if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
  575.                 else: tooltip = "click to toggle"
  576.                 BUT_TYPES[bool][i] = Draw.Toggle("", BEVT_BOOL + i,
  577.                     x, y, w, h, tog, tooltip)
  578.                 BGL.glRasterPos2i(x + w + 3, y + 5)
  579.                 Draw.Text(l[0].lower().replace('_', ' '))
  580.             i = -1
  581.             y -= 5
  582.         if data.has_key(int) and y > 0:
  583.             lst = data[int]
  584.             for l in lst:
  585.                 w = 70
  586.                 top += 1
  587.                 i += 1
  588.                 if top < SCROLL_DOWN: continue
  589.                 y -= h
  590.                 if y < yend: break
  591.                 val = data[int][i][1]
  592.                 if limits: min, max = limits[l[0]]
  593.                 else: min, max = 0, 10
  594.                 if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
  595.                 else: tooltip = "click / drag to change"
  596.                 BUT_TYPES[int][i] = Draw.Number("", BEVT_INT + i,
  597.                     x, y, w, h, val, min, max, tooltip)
  598.                 BGL.glRasterPos2i(x + w + 3, y + 3)
  599.                 Draw.Text(l[0].lower().replace('_', ' '))
  600.             i = -1
  601.             y -= 5
  602.         if data.has_key(float) and y > 0:
  603.             lst = data[float]
  604.             for l in lst:
  605.                 w = 70
  606.                 top += 1
  607.                 i += 1
  608.                 if top < SCROLL_DOWN: continue
  609.                 y -= h
  610.                 if y < yend: break
  611.                 val = data[float][i][1]
  612.                 if limits: min, max = limits[l[0]]
  613.                 else: min, max = 0.0, 1.0
  614.                 if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
  615.                 else: tooltip = "click and drag to change"
  616.                 BUT_TYPES[float][i] = Draw.Number("", BEVT_FLOAT + i,
  617.                     x, y, w, h, val, min, max, tooltip)
  618.                 BGL.glRasterPos2i(x + w + 3, y + 3)
  619.                 Draw.Text(l[0].lower().replace('_', ' '))
  620.             i = -1
  621.             y -= 5
  622.         if data.has_key(str) and y > 0:
  623.             lst = data[str]
  624.             for l in lst:
  625.                 top += 1
  626.                 i += 1
  627.                 if top < SCROLL_DOWN: continue
  628.                 y -= h
  629.                 if y < yend: break
  630.                 name = l[0].lower()
  631.                 is_dir = is_file = False
  632.                 if name.find('_dir', -4) > 0:    is_dir = True
  633.                 elif name.find('_file', -5) > 0: is_file = True
  634.                 w = WIDTH - 20
  635.                 wbrowse = 50
  636.                 if is_dir and w > wbrowse: w -= wbrowse
  637.                 if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
  638.                 else: tooltip = "click to write a new string"
  639.                 name = name.replace('_',' ') + ': '
  640.                 if len(l[1]) > MAX_STR_LEN:
  641.                     l[1] = l[1][:MAX_STR_LEN]
  642.                 BUT_TYPES[str][i] = Draw.String(name, BEVT_STR + i,
  643.                     x, y, w, h, l[1], MAX_STR_LEN, tooltip)
  644.                 if is_dir:
  645.                     Draw.PushButton('browse', BEVT_BROWSEDIR + i, x+w+1, y, wbrowse, h,
  646.                         'click to open a file selector (pick any file in the desired dir)')
  647.                 elif is_file:
  648.                     Draw.PushButton('browse', BEVT_BROWSEFILE + i, x + w + 1, y, 50, h,
  649.                         'click to open a file selector')
  650.  
  651.  
  652. def fit_scroll():
  653.     global SCROLL_DOWN, VARS_NUM
  654.     max = VARS_NUM - 1 # so last item is always visible
  655.     if SCROLL_DOWN > max:
  656.         SCROLL_DOWN = max
  657.     elif SCROLL_DOWN < 0:
  658.         SCROLL_DOWN = 0
  659.  
  660.  
  661. def event(evt, val): # input events
  662.  
  663.     global SCREEN, START_SCREEN, CONFIG_SCREEN
  664.     global SCROLL_DOWN, CFGKEY
  665.  
  666.     if not val: return
  667.  
  668.     if evt == Draw.ESCKEY:
  669.         if SCREEN == START_SCREEN: Draw.Exit()
  670.         else:
  671.             if CFGKEY.needs_update():
  672.                 if Draw.PupMenu('UPDATE?%t|Data was changed') == 1:
  673.                     CFGKEY.update()
  674.             SCREEN = START_SCREEN
  675.             SCROLL_DOWN = 0
  676.             Draw.Redraw()
  677.         return
  678.     elif evt == Draw.QKEY:
  679.         if SCREEN == CONFIG_SCREEN and CFGKEY.needs_update():
  680.             if Draw.PupMenu('UPDATE?%t|Data was changed') == 1:
  681.                 CFGKEY.update()
  682.         Draw.Exit()
  683.         return
  684.     elif evt == Draw.HKEY:
  685.         if SCREEN == START_SCREEN: show_help()
  686.         elif CFGKEY.scriptname: show_help(CFGKEY.scriptname)
  687.         return
  688.  
  689.     elif SCREEN == CONFIG_SCREEN:
  690.         if evt in [Draw.DOWNARROWKEY, Draw.WHEELDOWNMOUSE]:
  691.             SCROLL_DOWN += 1
  692.             fit_scroll()
  693.         elif evt in [Draw.UPARROWKEY, Draw.WHEELUPMOUSE]:
  694.             SCROLL_DOWN -= 1
  695.             fit_scroll()
  696.         elif evt == Draw.UKEY:
  697.             if CFGKEY.needs_update():
  698.                 CFGKEY.revert()
  699.         elif evt == Draw.RETKEY or evt == Draw.PADENTER:
  700.             if CFGKEY.needs_update():
  701.                 CFGKEY.update()
  702.         elif evt == Draw.DELKEY:
  703.             if CFGKEY.delete():
  704.                 reset()
  705.                 init_data()
  706.                 SCREEN = START_SCREEN
  707.                 SCROLL_DOWN = 0
  708.         else: return
  709.         Draw.Redraw()
  710.  
  711.  
  712. def button_event(evt): # gui button events
  713.  
  714.     global SCREEN, START_SCREEN, CONFIG_SCREEN, CFGKEY, DISK_UPDATE
  715.     global BEVT_KEYMENU, BUT_KEYMENU, BUT_TYPES, SCROLL_DOWN, GD, INDEX
  716.     global BEVT_EXIT, BEVT_BACK, BEVT_APPLY, BEVT_CANCEL, BEVT_HELP, FREEKEY_IDX
  717.  
  718.     if SCREEN == START_SCREEN:
  719.         for e in BEVT_KEYMENU:
  720.             if evt == e:
  721.                 index = e - 1
  722.                 k = BUT_KEYMENU[index].val - 1
  723.                 CFGKEY = Config(GD[LABELS[index]][k][0], index != FREEKEY_IDX)
  724.                 if CFGKEY.data:
  725.                     SCREEN = CONFIG_SCREEN
  726.                     Draw.Redraw()
  727.                     return
  728.         if evt == BEVT_EXIT:
  729.             Draw.Exit()
  730.         elif evt == BEVT_HELP:
  731.             show_help()
  732.         return
  733.  
  734.     elif SCREEN == CONFIG_SCREEN:
  735.         datatypes = CFGKEY.sorteddata
  736.         if evt >= BEVT_BROWSEFILE:
  737.             INDEX = evt - BEVT_BROWSEFILE
  738.             Window.FileSelector(fs_file_callback, 'Choose file')
  739.         elif evt >= BEVT_BROWSEDIR:
  740.             INDEX = evt - BEVT_BROWSEDIR
  741.             Window.FileSelector(fs_dir_callback, 'Choose any file')
  742.         elif evt >= BEVT_STR:
  743.             var = BUT_TYPES[str][evt - BEVT_STR].val
  744.             datatypes[str][evt - BEVT_STR][1] = var
  745.         elif evt >= BEVT_FLOAT:
  746.             var = BUT_TYPES[float][evt - BEVT_FLOAT].val
  747.             datatypes[float][evt - BEVT_FLOAT][1] = var
  748.         elif evt >= BEVT_INT:
  749.             var = BUT_TYPES[int][evt - BEVT_INT].val
  750.             datatypes[int][evt - BEVT_INT][1] = var
  751.         elif evt >= BEVT_BOOL:
  752.             var = datatypes[bool][evt - BEVT_BOOL][1]
  753.             if var == True: var = False
  754.             else: var = True
  755.             datatypes[bool][evt - BEVT_BOOL][1] = var
  756.  
  757.         elif evt == BEVT_BACK:
  758.             if SCREEN == CONFIG_SCREEN:
  759.                 SCREEN = START_SCREEN
  760.                 SCROLL_DOWN = 0
  761.                 Draw.Redraw()
  762.         elif evt == BEVT_EXIT:
  763.             if CFGKEY.needs_update():
  764.                 if Draw.PupMenu('UPDATE?%t|Data was changed') == 1:
  765.                     CFGKEY.update()
  766.             Draw.Exit()
  767.             return
  768.         elif evt == BEVT_APPLY:
  769.             if CFGKEY.needs_update():
  770.                 CFGKEY.update()
  771.         elif evt == BEVT_CANCEL:
  772.             if CFGKEY.needs_update():
  773.                 CFGKEY.revert()
  774.         elif evt == BEVT_DEL:
  775.             if CFGKEY.delete():
  776.                 reset()
  777.                 init_data()
  778.                 SCREEN = START_SCREEN
  779.                 SCROLL_DOWN = 0
  780.         elif evt == BEVT_DISK:
  781.             if DISK_UPDATE: DISK_UPDATE = False
  782.             else: DISK_UPDATE = True
  783.         elif evt == BEVT_HELP:
  784.             show_help(CFGKEY.scriptname)
  785.             return
  786.         else:
  787.             return
  788.     Draw.Redraw()
  789.  
  790. # End of definitions
  791.  
  792.  
  793. KEYS = get_keys()
  794.  
  795. if not KEYS:
  796.     Draw.PupMenu("NO DATA: please read this help screen")
  797.     Blender.ShowHelp('config.py')
  798. else:
  799.     fill_scripts_dict()
  800.     init_data()
  801.     Draw.Register(gui, event, button_event)
  802.